package com.francis.springbootcommonutil.encry;

import org.apache.commons.codec.binary.Hex;
import org.springframework.util.StringUtils;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class Md5Hash {

    private static final String hexDigits[] = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f" };

    public static byte[] md5HashByte(String str, String salt, int hashTimes) throws NoSuchAlgorithmException {
        if(StringUtils.isEmpty(str)){
            throw new NullPointerException("待加密字段为空");
        }
        if(StringUtils.isEmpty(salt)){
            throw new NullPointerException("加密字段为空");
        }

        hashTimes = Math.max(1, hashTimes);
        byte[] $hash = hash(str.getBytes(), salt.getBytes(), hashTimes);
        return new Hex().encode($hash);
    }

    private static byte[] hash(byte[] bytes, byte[] salt, int hashTimes) throws NoSuchAlgorithmException {
        MessageDigest digest = MessageDigest.getInstance("MD5");
        digest.reset();
        digest.update(salt);

        byte[] $hashed = digest.digest(bytes);
        int iterations = hashTimes - 1;
        for(int i = 0;i < iterations;i ++){
            digest.reset();
            $hashed = digest.digest($hashed);
        }
        return $hashed;
    }

    private static String byteToHex(byte b) {
        int n = b;
        if (n < 0)
            n += 256;
        int d1 = n / 16;
        int d2 = n % 16;
        return hexDigits[d1] + hexDigits[d2];
    }

    /**
     * 转成16进制字符串
     * @param bytes
     * @return
     */
    public static String byteArrayToHex(byte[] bytes){
        StringBuilder buffer = new StringBuilder();
        for(int i = 0;i < bytes.length; i++){
            buffer.append(byteToHex(bytes[i]));
        }
        return buffer.toString();
    }

    public static byte[] desByteCopy(byte[] bytes, int keySize){
        byte[] b = new byte[keySize];
        if(bytes.length > keySize){
            System.arraycopy(bytes, 0, b,0,keySize);
        }
        return b;
    }
}
